package com.chuangke.framework.service.impl;

import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Scope;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicInteger;
import org.springframework.stereotype.Service;

import com.chuangke.common.exception.ChuangkeException;

@Service
@Scope("prototype")
@ConditionalOnProperty(value="spring.cache.type",havingValue = "redis")
public class RedisRetryServiceImpl implements com.chuangke.framework.service.RetryService {

	private static final String RETRY_FAILED_COUNT = "RETRY:FAILED:COUNT:";// redis记录用户登录失败次数key

	@Autowired
	private RedisTemplate<String, ?> stringRedisTemplate;

	private int timeInterval = 10;// 重试计数时间间隔
	private int maxRetryTimes = 3;// 最大重试次数

	public int getTimeInterval() {
		return timeInterval;
	}

	public void setTimeInterval(int timeInterval) {
		this.timeInterval = timeInterval;
	}

	public int getMaxRetryTimes() {
		return maxRetryTimes;
	}

	public void setMaxRetryTimes(int maxRetryTimes) {
		this.maxRetryTimes = maxRetryTimes;
	}

	/**
	 * 检查是否重试超过上限
	 *
	 * @param name
	 * @param maxRetryTimes 最大重试次数
	 */
	@Override
	public void checkRetryTimes(String name, int maxRetryTimes) {
		String key = getKey(name);
		RedisAtomicInteger counter = getRedisCounter(key);

		if (counter.get() >= maxRetryTimes) {
			throw new ChuangkeException("超过重试次数，请稍后再试。");
		}
	}

	/**
	 * 登录失败计数
	 *
	 * @param name 用户名
	 * @return
	 */
	@Override
	public void retry(String name) {
		String key = getKey(name);

		RedisAtomicInteger counter = getRedisCounter(key);

		counter.getAndIncrement();// 失败次数 + 1
	}

	@Override
	public void retrySuccessed(String name) {
		String key = getKey(name);
		stringRedisTemplate.delete(key);
	}

	@Override
	public int getRetryTimes(String name) {
		String key = getKey(name);
		RedisAtomicInteger counter = getRedisCounter(key);
		return counter.get();
	}

	private String getKey(String name) {
		return RETRY_FAILED_COUNT + name;
	}

	/**
	 * 根据key获取计数器
	 *
	 * @param key key
	 * @return
	 */
	private RedisAtomicInteger getRedisCounter(String key) {
		RedisAtomicInteger counter = new RedisAtomicInteger(key, stringRedisTemplate.getConnectionFactory());
		if (counter.get() == 0) {
			// 设置过期时间，10分钟
			counter.expire(timeInterval, TimeUnit.MINUTES);
		}
		return counter;
	}
}
